package cn.keniykey.mc.landterritory.database;

import java.io.File;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.logging.Logger;

import org.bukkit.configuration.file.YamlConfiguration;

import cn.keniykey.mc.landterritory.LandTerritoryMain;
import cn.keniykey.mc.landterritory.toolkit.DebugUtil;

public final class DataBaseManager {
	private static AbDataBaseCore core;
	
	public static void closeDataBaseCore() {
		if(core == null) return;
		core.close();
		core = null;
	}
	public static void enableDataBaseCore() throws SQLException, ClassNotFoundException, IOException {
		if(core != null) return;
		final File databasefile = new File(LandTerritoryMain.getPlugin().getDataFolder(),"database.yml");
		if(!databasefile.exists()) initFile(databasefile);
		final YamlConfiguration yaml = YamlConfiguration.loadConfiguration(databasefile);
		core = getDataBaseCore(yaml, "basetype");
		core.initDataBase();
		try {
			if(copyDataBase(core, yaml)) {
				yaml.set("movebase", null);
				try {
					yaml.save(databasefile);
				}catch(Exception ex) {}
				LandTerritoryMain.getPlugin().getLogger().warning("数据库转移完毕，推荐手动核实一下数据(旧数据库没删除)");
			}else {
				DebugUtil.info("数据库指令[copydatabase]：没有需要转换的数据库");
			}
		}catch(SQLException sqlex) {
			sqlex.printStackTrace();
			LandTerritoryMain.getPlugin().getLogger().warning("数据库有可能在转移过程中失败，请检查数据库");
		}catch(Exception ex) {
			ex.printStackTrace();
			LandTerritoryMain.getPlugin().getLogger().warning("数据库转移失败，请确认是否输入了正确的原数据库类型");
		}
	}
	public static AbDataBaseCore getDataBaseCore() throws IOException{
		if(core != null) return core;
		throw new IOException("(database is not running)数据库未开启");
	}
	private static AbDataBaseCore getDataBaseCore(YamlConfiguration yaml,String str) throws ClassNotFoundException, IOException {
		final String sql = yaml.getString(str, "none");
		AbDataBaseCore usecore;
		switch(sql.toLowerCase()) {
		case "sqlite":
			usecore = initSqlite(yaml);
			break;
		case "mysql":
			usecore = initMySQL(yaml);
			break;
		case "mysql8.0":
			usecore = initMySQL8_0(yaml);
			break;
		default:
			throw new IOException("暂不支持 " + sql + " 类型数据库，目前可用有Sqlite,MySQL,MySQL8.0");
		}
		return usecore;
	}
	private static void initFile(File file) throws IOException {
		final YamlConfiguration yaml = new YamlConfiguration();
		yaml.set("basetype", "sqlite");
		yaml.set("movebase.basetype", "none");
		yaml.set("sqlite.path", "data");
		yaml.set("sqlite.file", "land.dat");
		yaml.set("mysql.basename", "minecraft");
		yaml.set("mysql.host", "localhost");
		yaml.set("mysql.port", 3306);
		yaml.set("mysql.user", "root");
		yaml.set("mysql.password", "12345678");
		yaml.set("mysql.usessl", false);
		yaml.set("mysql.timezone", "UTC");
		yaml.save(file);
	}
	private static AbDataBaseCore initSqlite(YamlConfiguration yaml) throws ClassNotFoundException {
		final File savepath = new File(yaml.getString("sqlite.path","data"));
		savepath.mkdirs();
		final AbDataBase database = new SqliteCore(new File(savepath,yaml.getString("sqlite.file","land.dat")));
		return new DataBaseCoreSqlite(database);
	}
	private static AbDataBaseCore initMySQL(YamlConfiguration yaml) throws ClassNotFoundException {
		final AbDataBase database = new MySQLCore(yaml.getString("mysql.host"), yaml.getInt("mysql.port"), yaml.getString("mysql.basename"), yaml.getString("mysql.user"),
				yaml.getString("mysql.password"));
		return new DataBaseCoreMySQL(database);
	}
	private static AbDataBaseCore initMySQL8_0(YamlConfiguration yaml) throws ClassNotFoundException {
		final AbDataBase database = new MySQLCore(yaml.getString("mysql.host"), yaml.getInt("mysql.port"), yaml.getString("mysql.basename"), yaml.getString("mysql.user"),
				yaml.getString("mysql.password"),yaml.getBoolean("mysql.usessl"),yaml.getString("mysql.timezone"));
		return new DataBaseCoreMySQL(database);
	}
	private static boolean copyDataBase(AbDataBaseCore dbc,YamlConfiguration yaml) throws ClassNotFoundException, SQLException, IOException {
		final String movebase_basetype = yaml.getString("movebase.basetype","none");
		if(movebase_basetype.equalsIgnoreCase("none")) return false;
		final AbDataBaseCore oldcore = getDataBaseCore(yaml, "movebase.basetype");
		final Statement oldsm = oldcore.getDataBase().getConnection().createStatement();
		try {
			final ResultSet old_table_rs = oldcore.getDataBase().getConnection().getMetaData().getTables(null, null, "%", null);
			final LinkedList<String> table_links = new LinkedList<>();
			try {
				while(old_table_rs.next()) table_links.add(old_table_rs.getString("TABLE_NAME"));
			}catch(SQLException sqlex) {
				table_links.clear();
				throw sqlex;
			}finally {
				try{
					old_table_rs.close();
				}catch(Exception ex) {
					DebugUtil.info("数据库中介指令[copydatabase]异常：无法关闭old_tables_rs");
					DebugUtil.info(ex);
				}
			}
			final Logger logger = LandTerritoryMain.getPlugin().getLogger();
			while(!table_links.isEmpty()) {
				final String table_name = table_links.removeFirst();
				if(!table_name.startsWith("land_")) continue;
				logger.warning("开始复制转移数据库表: " + table_name);
				final ResultSet rs = oldsm.executeQuery("select * from `" + table_name + "`;");
				try {
					final int columncount = rs.getMetaData().getColumnCount();
					final StringBuilder builder = new StringBuilder();
					builder.append("insert into `");
					builder.append(table_name);
					builder.append("` values(?");
					for(int index = 2; index <= columncount; index++) builder.append(",?");
					builder.append(");");
					final PreparedStatement ps = dbc.getDataBase().getConnection().prepareStatement(builder.toString());
					try {
						int amount = 0;
						while(rs.next()) {
							for(int www = 1; www <= columncount; www++) ps.setObject(www, rs.getObject(www));
							ps.addBatch();
							amount++;
							if((amount % 50) == 0) {
								ps.executeBatch();
								logger.warning("正在转移数据表 " + table_name + " 中，目前已转移 "+ amount + " 条");
							}
						}
						if((amount % 50) != 0) {
							ps.executeBatch();
						}
						logger.warning("转移数据表 " + table_name + " 完成，总共 "+ amount + " 条");
					}finally {
						try{
							ps.close();
						}catch(Exception ex) {
							DebugUtil.info("数据库中介指令[copydatabase]异常：无法关闭copy_insert_ps");
							DebugUtil.info(ex);
						}
					}
				}finally {
					try {
						rs.close();
					}catch(Exception ex) {
						DebugUtil.info("数据库中介指令[copydatabase]异常：无法关闭old_table_rs");
						DebugUtil.info(ex);
					}
				}
			}
		}finally {
			try {
				oldsm.close();
			}catch(Exception ex) {
				DebugUtil.info("数据库中介指令[copydatabase]异常：无法关闭old_sm");
				DebugUtil.info(ex);
			}
			try {
				oldcore.close();
			}catch(Exception ex) {
				DebugUtil.info("数据库中介指令[copydatabase]异常：无法关闭old_core");
				DebugUtil.info(ex);
			}
		}
		return true;
	}
}